﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using Device.Base.Comm;

namespace Device.Base
{
    /// <summary>
    /// 结果状态
    /// </summary>
    public enum ResultState
    {
        [Description("成功")]
        Success,
        [Description("失败")]
        Fail,
        [Description("端口占用")]
        Occupy,
        [Description("等待超时")]
        OverTime
    }
    /// <summary>
    /// 通讯基础类
    /// </summary>
    public class CommBase
    {
        /// <summary>
        /// 日志
        /// </summary>
        public event Action<string> LogEvent;
        /// <summary>
        /// 通信状态变化
        /// </summary>
        public event Action<bool> StateChangeEvent;


        //protected readonly ILog _log = LogFactory.GetLogger("");
        public CommBase(ITransmission communication)
        {
            Communication = communication;
        }

        /// <summary>
        /// 通信 传输
        /// </summary>
        public ITransmission Communication;
        public bool Open()
        {
            var result = Communication.Open();
            ConnectionState = Communication.IsOpen();
            if (ConnectionState)
            {
                Communication.Received += OnReceived;
            }
            return result;
        }
        public bool Close()
        {
            Communication.Received -= OnReceived;
            var result = Communication.Close();
            ConnectionState = Communication.IsOpen();
            return result;
        }


        private void OnReceived(byte[] data)
        {
            Log("接受", data);
            StateChangeEvent?.Invoke(true);
            if (WaitState)
            {
                _cache.AddRange(data);
                Signal?.Release();//释放信号 
            }
            else
            {
                Received(data);
            }


        }

        protected virtual void Received(byte[] data)
        {
        }

        /// <summary>
        /// 连接状态
        /// </summary>
        public bool ConnectionState { set; get; }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public bool Send(byte[] buffer)
        {
            if (!ConnectionState)
            {
                Communication.Open();
            }

            if (ConnectionState)
            {

                if (Communication.Send(buffer))
                {

                    Log("发送", buffer);
                    return true;
                }
            }
            Log("发送失败", buffer);
            return false;

        }

        #region 同步命令
        /// <summary>
        /// 等待时间 秒
        /// </summary>
        protected int WaitTime = 1;
        /// <summary>
        /// 同步信号量
        /// </summary>
        protected Semaphore Signal;
        /// <summary>
        /// 同步等待状态
        /// </summary>
        protected bool WaitState;

        protected object OLock = new object();

        /// <summary>
        /// 缓存
        /// </summary>
        private List<byte> _cache = new List<byte>();

        private void Log(string name, byte[] buffer)
        {
            string logContent = "";
            foreach (var item in buffer)
            {
                logContent += item.ToString("X2") + " ";
            }
            LogEvent?.Invoke(name + ":" + logContent);
            //  _log.Debug(name + ":" + logContent);
        }

        /// <summary>
        /// 同步命令 
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="callbackFunc">回调函数</param>
        /// <returns></returns>
        protected ResultState SendSync(byte[] buffer, Func<byte[], bool> callbackFunc)
        {

            ResultState result;
            //if (!WaitState)
            lock (OLock)
            {
                if (Send(buffer))
                {

                    WaitState = true;

                    _cache = new List<byte>();
                    Signal = new Semaphore(0, 1);
                    //等待信号 超时返回
                    result = Signal.WaitOne(new TimeSpan(0, 0, WaitTime)) ? ResultState.Success : ResultState.OverTime;
                    WaitState = false;
                    Signal = null;

                    //结果处理
                    if (result == ResultState.Success)
                    {

                        if (callbackFunc != null)
                        {
                            if (!callbackFunc.Invoke(_cache.ToArray()))
                            {
                                result = ResultState.Fail;//判断是否有结果值
                            }
                        }
                    }
                    else if (result == ResultState.OverTime)
                    {
                        Log("超时", _cache.ToArray());
                    }

                }
                else
                    result = ResultState.Fail;
            }
            return result;
        }

        #endregion

    }
}
